<?php

declare(strict_types=1);

namespace app\command;

use app\api\logic\LogicalProcess;
use app\api\model\DtsGame;
use app\api\model\UserPointsLog;
use app\api\services\DtsService;
use Fund\Points\Add;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\facade\Cache;
use think\facade\Db;
use think\facade\Log;

class GameDts extends Command
{

    protected $killer_index = 0;

    protected function configure()
    {
        $this->setName('game:dts')
            ->setDescription('dts');
    }

    protected function execute(Input $input, Output $output)
    {
        $this->init();
        while (true) {
            sleep(1);

            $game = $this->getLastGame();
            if (!$game) {
//                $this->debugInfo('Game empty');
                continue;
            }

            $this->debugInfo(sprintf('【%s】calc start', $game->id));

            //封盘
            $this->lock();

            //结算
            $result = $this->calc($game);

            //结算失败，重试
            if (!$result) continue;

            $this->debugInfo(sprintf('【%s】calc end', $game->id));

            //等待前端的动画
            sleep(22);

            //添加新的一期
            $this->addGame($this->killer_index);

            //开盘
            $this->unlock();

            //删除上期缓存数据
            DtsService::deleteGameCache($game);
        }
    }


    public function calc(DtsGame $game)
    {
        try {
            $killer_index = $this->getKiller($game);
            //被刀房间的所有投注
            $total_killer_amount = $game->records()
                ->where('room_id', $killer_index)
                ->sum('amount');

            //所有房间的投注
            $total_amount = $game->records()->sum('amount');
            $total_people = 0;
            $total_bonus = 0;
            foreach ($game->records as $joinUser) {
                $total_people++;
                $joinUser->killer_room = $killer_index;

                //被刀房间的人
                if ($joinUser->room_id == $killer_index) {
                    $joinUser->state = 2;
                    $joinUser->save();
                    //补偿玩家的金箍棒
                    (new LogicalProcess())->wallletChange($joinUser->user_id,$joinUser->amount,4,1,2,'大逃杀补偿金箍棒');
//                    $this->debugInfo($joinUser->user_id . ' kill');
                    continue;
                }
                //获取游戏配置
                $dfjScale = Db::name("game_config")->where("id", 1)->value("dtc_dfj_total");
                //获取需要给到大反击的部分
                $dfjGetTotal = bcmul((string)$total_killer_amount, bcdiv($dfjScale, '100', 2), 2);
                //修改大反击奖池
                Db::name("game_config")->where("id", 1)->inc("dfj_prize_pool", (float)$dfjGetTotal);
                //需要瓜分的金额
                $carve = bcsub((string)$total_killer_amount, $dfjGetTotal, 6);

                //发放奖金
                $bonus = sprintf("%.6f", substr(sprintf("%.6f", $carve), 0, -2));
                if ($joinUser->user) {
                    //本金加利润
                    $add = new Add($joinUser->user, bcadd($bonus, (string)$joinUser->amount, 2), UserPointsLog::BUSINESS_TYPE_GAME_DTS_IN, ['target_id' => $joinUser->id]);
                    $add->action();
                }

                //累计共产生多少奖金
                $total_bonus = bcadd((string)$total_bonus, $bonus, 2);
                $joinUser->bonus = $bonus;
                $joinUser->state = 1;
                $joinUser->save();
                //更新自己的奖金
                DtsService::updateBonus($joinUser->user, $game, $bonus);
//                $this->debugInfo($joinUser->user_id . ' bonus ' . $bonus);
            }

            $game->state = 3;
            $game->end_time = time();
            $game->total_people = $total_people;
            $game->total_amount = $total_amount;
            $game->total_bonus = $total_bonus;
            $game->killer_room = $killer_index;
            $game->total_killer_amount = $total_killer_amount;
            $game->save();
            $this->killer_index = $killer_index;

            Db::commit();
            return true;
        } catch (\Exception $exception) {
            Db::rollback();
            $this->debugInfo($exception->getMessage());
            Log::error($exception->getMessage());
            return false;
        }
    }


    public function getKiller(DtsGame $game): int
    {
        $room_ids = $game->records()->column('room_id');
        return $room_ids[array_rand($room_ids, 1)];
    }

    public function getLastGame()
    {
        return DtsGame::where('state', 2)
            ->with('records')
            ->where('end_time', '<=', time())
            ->find();
    }


    public function init()
    {
//        $count = DtsGame::count();
        $count = DtsGame::where('state', '<>', 3)->count();
        if ($count === 0) {
            $this->addGame();
        }
    }

    public function lock()
    {
        $this->debugInfo('=====lock=====');
        Cache::store("redis")->set('game_dts_lock_flag', time(), 10);
    }

    public function unlock()
    {
        $this->debugInfo('=====unlock=====');
        Cache::store("redis")->delete('game_dts_lock_flag');
    }

    public function addGame($pre_killer_room = 0)
    {
        $game = DtsGame::create([
            'state' => 1,
            'killer_room' => 0,
            'pre_killer_room' => $pre_killer_room,
            'total_people' => 0,
            'total_amount' => 0,
            'total_bonus' => 0,
        ]);
        Cache::store("redis")->set('game_dts_last_game_id', $game->id);
        return $game;
    }

    public function debugInfo(string $info)
    {
//        $this->output->info(sprintf('[%s] %s', date('Y-m-d H:i:s'), $info));
    }

}